vue 作用域插槽

默认插槽和具名插槽这里就不多说了,大家直接去看官网的例子就好插槽,我们来说说 2.1.0+ 新增的比较难理解的作用域插槽。

官网例子

有的时候你希望提供的组件带有一个可从子组件获取数据的可复用的插槽。例如一个简单的 组件的模板可能包含了如下代码:

1
2
3
4
5
6
7
8
<ul>
<li
v-for="todo in todos"
v-bind:key="todo.id"
>
{{ todo.text }}
</li>
</ul>

但是在我们应用的某些部分,我们希望每个独立的待办项渲染出和todo.text不太一样的东西。这也是作用域插槽的用武之地。

为了让这个特性成为可能,你需要做的全部事情就是将待办项内容包裹在一个 元素上,然后将所有和其上下文相关的数据传递给这个插槽:在这个例子中,这个数据是 todo 对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
<ul>
<li
v-for="todo in todos"
v-bind:key="todo.id"
>
<!-- 我们为每个 todo 准备了一个插槽,-->
<!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
<slot v-bind:todo="todo">
<!-- 回退的内容 -->
{{ todo.text }}
</slot>
</li>
</ul>

现在当我们使用 组件的时候,我们可以选择为待办项定义一个不一样的

1
2
3
4
5
6
7
8
9
<todo-list v-bind:todos="todos">
<!-- 将 `slotProps` 定义为插槽作用域的名字 -->
<template slot-scope="slotProps">
<!-- 为待办项自定义一个模板,-->
<!-- 通过 `slotProps` 定制每个待办项。-->
<span v-if="slotProps.todo.isComplete"></span>
{{ slotProps.todo.text }}
</template>
</todo-list>

注意:在 2.5.0+,slot-scope 不再限制在

自己的理解

我对官网例子的理解是:子组件从数据源中获取数据,然后再回传一份数据给父组件来做样式层面的渲染:

对此我写了一个简单的小例子是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Scioed Slots</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="root">
<child>
<template slot-scope="slotProps">
<li>{{slotProps.item}}</li>
</template>
</child>
</div>
<script>
Vue.component('child',{
data:function(){
return{
list:["苹果","西瓜","橘子","香蕉"]
}
},
template: `<div>
<ul>
<slot
v-for="item of list"
:item=item
></slot>
</ul>
</div>`
});

var vm = new Vue({
el: '#root',
});
</script>
</body>
</html>

子组件在 slot 中通过 v-for 遍历数据,并把 item 回传给父组件,父组件通过 slot-scope 自定义一个属性接受子组件回传的数据对象。

到这里,大家可能会有一个疑问:正常不是应该父组件获取数据后,再交给子组件来渲染的吗?

我个人的理解是:为了使用起来更加灵活。比如你写了一个弹窗组件,发布后,你的使用者想自定义弹窗部分的内容或样式,比如自己定义标题和多个按钮等 dom 结构以及相关样式。此时,你可能就需要使用这个功能了。

是不是感觉比看完官网的更清楚一些了?



完~